package com.ruoyi.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.business.mapper.WsdCanteenBalanceMapper;
import com.ruoyi.business.service.IWsdCanteenBalanceService;
import com.ruoyi.business.service.IWsdRechargeRefundService;
import com.ruoyi.business.service.IWsdStudentsService;
import com.ruoyi.common.core.domain.dto.WsdCanteensOrderDTO;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.WsdCanteenBalance;
import com.ruoyi.common.core.domain.entity.WsdStudents;
import com.ruoyi.common.core.domain.vo.OrderPeopleNumVO;
import com.ruoyi.common.core.domain.vo.RechargeRefundVO;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.date.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-22
 */
@Service
@Slf4j
public class WsdCanteenBalanceServiceImpl extends ServiceImpl<WsdCanteenBalanceMapper, WsdCanteenBalance> implements IWsdCanteenBalanceService
{
    @Autowired
    private WsdCanteenBalanceMapper wsdCanteenBalanceMapper;
    @Autowired
    private IWsdRechargeRefundService wsdRechargeRefundService;
    @Autowired
    private IWsdStudentsService wsdStudentsService;
    /**
     * 查询饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     *
     * @param balanceId 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额主键
     * @return 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     */
    @Override
    public WsdCanteenBalance selectWsdCanteenBalanceByBalanceId(String balanceId)
    {
        return wsdCanteenBalanceMapper.selectWsdCanteenBalanceByBalanceId(balanceId);
    }

    /**
     * 查询饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额列表
     *
     * @param wsdCanteenBalance 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     * @return 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     */
    @Override
    public List<WsdCanteenBalance> selectWsdCanteenBalanceList(WsdCanteenBalance wsdCanteenBalance)
    {
        return wsdCanteenBalanceMapper.selectWsdCanteenBalanceList(wsdCanteenBalance);
    }

    /**
     * 新增饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     *
     * @param wsdCanteenBalance 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     * @return 结果
     */
    @Override
    public int insertWsdCanteenBalance(WsdCanteenBalance wsdCanteenBalance)
    {
        wsdCanteenBalance.setCreateTime(DateUtils.getNowDate());
        return wsdCanteenBalanceMapper.insertWsdCanteenBalance(wsdCanteenBalance);
    }

    /**
     * 修改饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     *
     * @param wsdCanteenBalance 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     * @return 结果
     */
    @Override
    public int updateWsdCanteenBalance(WsdCanteenBalance wsdCanteenBalance)
    {
        wsdCanteenBalance.setUpdateTime(DateUtils.getNowDate());
        return wsdCanteenBalanceMapper.updateWsdCanteenBalance(wsdCanteenBalance);
    }

    /**
     * 批量删除饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额
     *
     * @param balanceIds 需要删除的饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额主键
     * @return 结果
     */
    @Override
    public int deleteWsdCanteenBalanceByBalanceIds(String[] balanceIds)
    {
        return wsdCanteenBalanceMapper.deleteWsdCanteenBalanceByBalanceIds(balanceIds);
    }

    /**
     * 删除饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额信息
     *
     * @param balanceId 饭堂余额，记录学生在学校饭堂的总充值金额和总退款金额主键
     * @return 结果
     */
    @Override
    public int deleteWsdCanteenBalanceByBalanceId(String balanceId)
    {
        return wsdCanteenBalanceMapper.deleteWsdCanteenBalanceByBalanceId(balanceId);
    }

    /**
     * 更新或创建学生充值记录
     *
     * @param studentId   学生ID
     * @param schoolId   学校ID
     * @param amount 充值金额（以元为单位，充值总是正数）
     */
    @Override
    public void rechargeBalance(Long studentId, Long schoolId, BigDecimal amount,Integer mealType) {
        //获取配置ConfigId
        String currentDateString = DateTimeUtil.getCurrentDateString();
        RechargeRefundVO rechargeRefundVO = wsdRechargeRefundService.existsActiveSemester(schoolId,currentDateString);
        // 构建查询条件
        LambdaQueryWrapper<WsdCanteenBalance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WsdCanteenBalance::getStudentId, studentId)
                .eq(WsdCanteenBalance::getSchoolId, schoolId);
        if (rechargeRefundVO.getConfigId() != null) {
            queryWrapper.eq(WsdCanteenBalance::getConfigId, rechargeRefundVO.getConfigId());
        }

        // 查询学生在该学校的余额记录
        WsdCanteenBalance balance = this.getOne(queryWrapper, false);
        WsdStudents wsdStudents = wsdStudentsService.selectWsdStudentsById(studentId);
        // 如果余额记录不存在，创建新记录
        if (balance == null) {
            log.info("未找到学生ID: {}, 学校ID: {} 的余额记录，将创建新记录。", studentId, schoolId);
            balance = new WsdCanteenBalance();
            balance.setStudentId(String.valueOf(studentId));
            balance.setSchoolId(String.valueOf(schoolId));
            balance.setIdentityNumber(wsdStudents.getIdentityNumber()); // 需要确保身份证号可提供或处理方式
            balance.setConfigId( rechargeRefundVO.getConfigId() );
            balance.setClassId( wsdStudents.getClassId() );
            // 初始化所有相关金额字段
            balance.setTotalRechargeAmountBreakfast(BigDecimal.ZERO);
            balance.setTotalRechargeAmountLunch(BigDecimal.ZERO);
            balance.setTotalRechargeAmountDinner(BigDecimal.ZERO);
            balance.setTotalRefundAmountBreakfast(BigDecimal.ZERO);
            balance.setTotalRefundAmountLunch(BigDecimal.ZERO);
            balance.setTotalRefundAmountDinner(BigDecimal.ZERO);
            balance.setBalanceBreakfast(BigDecimal.ZERO);
            balance.setBalanceLunch(BigDecimal.ZERO);
            balance.setBalanceDinner(BigDecimal.ZERO);

            BigDecimal balanceBreakfast = BigDecimal.ZERO;
            BigDecimal balanceLunch = BigDecimal.ZERO;
            BigDecimal balanceDinner = BigDecimal.ZERO;
            if (mealType == 3){
                balanceBreakfast = rechargeRefundVO.getTotalBreakfastFee();
                balanceLunch = rechargeRefundVO.getTotalLunchFee();
                balanceDinner = rechargeRefundVO.getDinnerFee();
            }
            // 根据餐段类型更新余额和充值金额
            updateBalanceByMealType(balance, mealType, amount,balanceBreakfast,balanceLunch,balanceDinner);
            // 保存新的余额记录
            this.save(balance);
            log.info("创建新记录并成功充值，学生ID: {}, 学校ID: {}, 充值金额: {}, 餐段: {}", studentId, schoolId, amount, mealType);
        } else {
            BigDecimal balanceBreakfast = BigDecimal.ZERO;
            BigDecimal balanceLunch = BigDecimal.ZERO;
            BigDecimal balanceDinner = BigDecimal.ZERO;
            if (mealType == 3){
                balanceBreakfast = rechargeRefundVO.getTotalBreakfastFee();
                balanceLunch = rechargeRefundVO.getTotalLunchFee();
                balanceDinner = rechargeRefundVO.getDinnerFee();
            }
            // 如果记录存在，更新余额和充值金额
            updateBalanceByMealType(balance, mealType, amount,balanceBreakfast,balanceLunch,balanceDinner);
            // 更新现有余额记录
            wsdCanteenBalanceMapper.updateBalanceByMealTypeById(balance);
            log.info("更新记录并成功充值，学生ID: {}, 学校ID: {}, 充值金额: {}, 餐段: {}", studentId, schoolId, amount, mealType);
        }
    }

    @Override
    public void rechargeBalance1(Long studentId, Long schoolId, BigDecimal amount,BigDecimal Breakfast,BigDecimal Lunch,BigDecimal Dinner,Integer mealType) {
        //获取配置ConfigId
        String currentDateString = DateTimeUtil.getCurrentDateString();
        RechargeRefundVO rechargeRefundVO = wsdRechargeRefundService.existsActiveSemester(schoolId,currentDateString);
        // 构建查询条件
        LambdaQueryWrapper<WsdCanteenBalance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WsdCanteenBalance::getStudentId, studentId)
                .eq(WsdCanteenBalance::getSchoolId, schoolId);
        if (rechargeRefundVO.getConfigId() != null) {
            queryWrapper.eq(WsdCanteenBalance::getConfigId, rechargeRefundVO.getConfigId());
        }

        // 查询学生在该学校的余额记录
        WsdCanteenBalance balance = this.getOne(queryWrapper, false);
        WsdStudents wsdStudents = wsdStudentsService.selectWsdStudentsById(studentId);
        // 如果余额记录不存在，创建新记录
        if (balance == null) {
            log.info("未找到学生ID: {}, 学校ID: {} 的余额记录，将创建新记录。", studentId, schoolId);
            balance = new WsdCanteenBalance();
            balance.setStudentId(String.valueOf(studentId));
            balance.setSchoolId(String.valueOf(schoolId));
            balance.setIdentityNumber(wsdStudents.getIdentityNumber()); // 需要确保身份证号可提供或处理方式
            balance.setConfigId( rechargeRefundVO.getConfigId() );
            balance.setClassId( wsdStudents.getClassId() );
            // 初始化所有相关金额字段
            balance.setTotalRechargeAmountBreakfast(BigDecimal.ZERO);
            balance.setTotalRechargeAmountLunch(BigDecimal.ZERO);
            balance.setTotalRechargeAmountDinner(BigDecimal.ZERO);
            balance.setTotalRefundAmountBreakfast(BigDecimal.ZERO);
            balance.setTotalRefundAmountLunch(BigDecimal.ZERO);
            balance.setTotalRefundAmountDinner(BigDecimal.ZERO);
            balance.setBalanceBreakfast(BigDecimal.ZERO);
            balance.setBalanceLunch(BigDecimal.ZERO);
            balance.setBalanceDinner(BigDecimal.ZERO);
            BigDecimal balanceBreakfast = BigDecimal.ZERO;
            BigDecimal balanceLunch = BigDecimal.ZERO;
            BigDecimal balanceDinner = BigDecimal.ZERO;
            // 根据餐段类型更新余额和充值金额
            updateBalanceByMealType(balance, mealType, amount,Breakfast,Lunch,Dinner);
            // 保存新的余额记录
            this.save(balance);
            log.info("创建新记录并成功充值，学生ID: {}, 学校ID: {}, 充值金额: {}, 餐段: {}", studentId, schoolId, amount, mealType);
        } else {
            BigDecimal balanceBreakfast = BigDecimal.ZERO;
            BigDecimal balanceLunch = BigDecimal.ZERO;
            BigDecimal balanceDinner = BigDecimal.ZERO;
            // 如果记录存在，更新余额和充值金额
            updateBalanceByMealType(balance, mealType, amount,Breakfast,Lunch,Dinner);
            // 更新现有余额记录
            wsdCanteenBalanceMapper.updateBalanceByMealTypeById(balance);
            log.info("更新记录并成功充值，学生ID: {}, 学校ID: {}, 充值金额: {}, 餐段: {}", studentId, schoolId, amount, mealType);
        }
    }
    /**
     * 根据餐段更新对应的余额和充值金额。
     * @param balance 账户余额对象
     * @param mealType 餐段类型（"breakfast", "lunch", "dinner"）
     * @param amount 充值金额
     */
    private void updateBalanceByMealType(WsdCanteenBalance balance, Integer mealType, BigDecimal amount, BigDecimal balanceBreakfast, BigDecimal balanceLunch, BigDecimal balanceDinner) {
        switch (mealType) {
            case 0:
                // 更新早餐总充值金额和当前余额
                balance.setTotalRechargeAmountBreakfast(balance.getTotalRechargeAmountBreakfast().add(amount));
                balance.setBalanceBreakfast(balance.getBalanceBreakfast().add(amount));
                log.info("更新早餐充值金额和余额，学生ID: {}, 早餐总充值金额: {}, 早餐当前余额: {}", balance.getStudentId(), balance.getTotalRechargeAmountBreakfast(), balance.getBalanceBreakfast());
                break;
            case 1:
                // 更新午餐总充值金额和当前余额
                balance.setTotalRechargeAmountLunch(balance.getTotalRechargeAmountLunch().add(amount));
                balance.setBalanceLunch(balance.getBalanceLunch().add(amount));
                log.info("更新午餐充值金额和余额，学生ID: {}, 午餐总充值金额: {}, 午餐当前余额: {}", balance.getStudentId(), balance.getTotalRechargeAmountLunch(), balance.getBalanceLunch());
                break;
            case 2:
                // 更新晚餐总充值金额和当前余额
                balance.setTotalRechargeAmountDinner(balance.getTotalRechargeAmountDinner().add(amount));
                balance.setBalanceDinner(balance.getBalanceDinner().add(amount));
                log.info("更新晚餐充值金额和余额，学生ID: {}, 晚餐总充值金额: {}, 晚餐当前余额: {}", balance.getStudentId(), balance.getTotalRechargeAmountDinner(), balance.getBalanceDinner());
                break;
            case 3:
                balance.setTotalRechargeAmountBreakfast(balance.getTotalRechargeAmountBreakfast().add(balanceBreakfast));
                balance.setBalanceBreakfast(balance.getBalanceBreakfast().add(balanceBreakfast));
                balance.setTotalRechargeAmountLunch(balance.getTotalRechargeAmountLunch().add(balanceLunch));
                balance.setBalanceLunch(balance.getBalanceLunch().add(balanceLunch));
                // 更新晚餐总充值金额和当前余额
                balance.setTotalRechargeAmountDinner(balance.getTotalRechargeAmountDinner().add(balanceDinner));
                balance.setBalanceDinner(balance.getBalanceDinner().add(balanceDinner));
                log.info("更新晚餐充值金额和余额，学生ID: {}, 晚餐总充值金额: {}, 晚餐当前余额: {}", balance.getStudentId(), balance.getTotalRechargeAmountDinner(), balance.getBalanceDinner());
                break;
            default:
                throw new IllegalArgumentException("无效的餐段类型: " + mealType);
        }

        // 更新最后一次充值时间
        balance.setLastRechargeTime(LocalDateTime.now());
        log.info("更新最后一次充值时间为: {}", balance.getLastRechargeTime());
    }

    /**
     * 处理学生退款操作，确保余额足够后进行扣减
     * @param studentId 学生的唯一标识ID
     * @param schoolId 学校的唯一标识ID
     * @param amount 退款金额（以元为单位，应为正数）
     */
    @Transactional
    public void refundBalance(Long studentId, Long schoolId, BigDecimal amount,Integer mealType) {
        // 构建查询条件
        LambdaQueryWrapper<WsdCanteenBalance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WsdCanteenBalance::getStudentId, studentId)
                .eq(WsdCanteenBalance::getSchoolId, schoolId);

        // 查询学生在该学校的余额记录
        WsdCanteenBalance balance = this.getOne(queryWrapper,false);

        // 检查余额记录是否存在且余额是否足够进行退款
        if (balance == null) {
            log.error("未找到学生ID: {}, 学校ID: {} 的余额记录，无法进行退款。", studentId, schoolId);
            throw new IllegalStateException("余额记录不存在，无法进行退款");
        }

        switch (mealType) {
            case 0:
                if (balance.getBalanceBreakfast().compareTo(amount) < 0) {
                    log.error("早餐余额不足，无法进行退款，学生ID: {}, 退款金额: {}, 当前早餐余额: {}", studentId, amount, balance.getBalanceBreakfast());
                    throw new IllegalStateException("早餐余额不足，无法进行退款");
                }
                balance.setTotalRefundAmountBreakfast(balance.getTotalRefundAmountBreakfast().add(amount));
                balance.setBalanceBreakfast(balance.getBalanceBreakfast().subtract(amount));
                log.info("更新早餐退款金额和余额，学生ID: {}, 早餐总退款金额: {}, 早餐当前余额: {}", balance.getStudentId(), balance.getTotalRefundAmountBreakfast(), balance.getBalanceBreakfast());
                break;
            case 1:
                if (balance.getBalanceLunch().compareTo(amount) < 0) {
                    log.error("午餐余额不足，无法进行退款，学生ID: {}, 退款金额: {}, 当前午餐余额: {}", studentId, amount, balance.getBalanceLunch());
                    throw new IllegalStateException("午餐余额不足，无法进行退款");
                }
                balance.setTotalRefundAmountLunch(balance.getTotalRefundAmountLunch().add(amount));
                balance.setBalanceLunch(balance.getBalanceLunch().subtract(amount));
                log.info("更新午餐退款金额和余额，学生ID: {}, 午餐总退款金额: {}, 午餐当前余额: {}", balance.getStudentId(), balance.getTotalRefundAmountLunch(), balance.getBalanceLunch());
                break;
            case 2:
                if (balance.getBalanceDinner().compareTo(amount) < 0) {
                    log.error("晚餐余额不足，无法进行退款，学生ID: {}, 退款金额: {}, 当前晚餐余额: {}", studentId, amount, balance.getBalanceDinner());
                    throw new IllegalStateException("晚餐余额不足，无法进行退款");
                }
                balance.setTotalRefundAmountDinner(balance.getTotalRefundAmountDinner().add(amount));
                balance.setBalanceDinner(balance.getBalanceDinner().subtract(amount));
                log.info("更新晚餐退款金额和余额，学生ID: {}, 晚餐总退款金额: {}, 晚餐当前余额: {}", balance.getStudentId(), balance.getTotalRefundAmountDinner(), balance.getBalanceDinner());
                break;
            default:
                throw new IllegalArgumentException("无效的餐段类型: " + mealType);
        }

        // 更新最后一次退款时间
        balance.setLastRefundTime(LocalDateTime.now());
        log.info("更新最后一次退款时间为: {}", balance.getLastRefundTime());

        // 更新现有余额记录
        wsdCanteenBalanceMapper.updateBalanceByMealTypeById(balance);
        log.info("成功退款，学生ID: {}, 学校ID: {}, 退款金额: {}, 餐段: {}", studentId, schoolId, amount, mealType);
    }

    /**
     * 查询学校订餐人数
     *
     * @param schoolId
     * @return
     */
    @Override
    public Integer selectStudentCountBySchool(Long schoolId) {
        return wsdCanteenBalanceMapper.selectStudentCountBySchool(schoolId);
    }

    /**
     * 订餐
     */
    @Override
    public OrderPeopleNumVO orderPeopleNum(WsdCanteensOrderDTO wsdCanteensOrderDTO){
        if (wsdCanteensOrderDTO.getStartDate()!=null&&wsdCanteensOrderDTO.getEndDate()!=null){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            // 解析日期部分
            LocalDate startLocalDate = LocalDate.parse(wsdCanteensOrderDTO.getStartDate(), formatter);
            LocalDate endLocalDate = LocalDate.parse(wsdCanteensOrderDTO.getEndDate(), formatter);

            // 设置开始时间为当天的00:00:00
            LocalDateTime startDate = startLocalDate.atStartOfDay();

            // 设置结束时间为当天的23:59:59
            LocalDateTime endDate = endLocalDate.atTime( LocalTime.MAX);
            wsdCanteensOrderDTO.setStartTime( startDate );
            wsdCanteensOrderDTO.setEndTime( endDate );
        }
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        if (!sysUser.isAdmin()||wsdCanteensOrderDTO.getSchoolId()!=null) {
            //获取配置Id
            //获取配置ConfigId
            String currentDateString = DateTimeUtil.getCurrentDateString();
            RechargeRefundVO rechargeRefundVO = wsdRechargeRefundService.existsActiveSemester( wsdCanteensOrderDTO.getSchoolId(), currentDateString );
            wsdCanteensOrderDTO.setConfigId( rechargeRefundVO.getConfigId() );
            OrderPeopleNumVO orderPeopleNumVO = wsdCanteenBalanceMapper.orderPeopleNum( wsdCanteensOrderDTO );
            if (rechargeRefundVO.getTotalBreakfastFee().compareTo( BigDecimal.ZERO ) == 0) {
                orderPeopleNumVO.setBreakfastNum( 0 );
            }
            if (rechargeRefundVO.getTotalLunchFee().compareTo( BigDecimal.ZERO ) == 0) {
                orderPeopleNumVO.setLunchNum( 0 );
            }
            if (rechargeRefundVO.getTotalDinnerFee().compareTo( BigDecimal.ZERO ) == 0) {
                orderPeopleNumVO.setDinnerNum( 0 );
            }
            return orderPeopleNumVO;
        }else {
            OrderPeopleNumVO orderPeopleNumVO = wsdCanteenBalanceMapper.orderPeopleNum( wsdCanteensOrderDTO );
            return orderPeopleNumVO;
        }
    }
}
